﻿/* $Author: alexander@bsrgin.ru $
 * $Id: LabyrinthInnerView.java 16 2011-11-17 21:32:19Z alexander@bsrgin.ru $
 * 
 * Описание view (с лабиринтом), по которому человек водит пальцем.
 */
package ru.habrahabr.prettyalarm;

import ru.habrahabr.prettyalarm.LabyrinthModel.Point;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * View, отрисовывающее лабиринт и уведомляющее модель лабиринта о событиях
 * взаимодействия с пользователем.
 * @author basargin
 */
public class LabyrinthInnerView extends View
{
	/** радиус бегунка */
	private final static int RUNNER_RADIUS = 30;
	/** толщина линий (стенок) лабиринта */
	private final static int ROUTE_WIDTH = 8;
	/** радиус узлов на границах лабиринта */
	private final static int ROUTE_TAIL_RADIUS = 15;
	/** радиус узлов лабиринта */
	private final static int ROUTE_NODE_RADIUS = ROUTE_WIDTH-2;
	/** допуск прохождения лабиринта, чем меньше допуск, тем сложнее проходить лабиринт*/
	private static final int ALLOWABLE_RUNNER_BOUNDS = 40; // TODO вычислить толщину пальца
	
	private float dip_scale;
	private int scalled_runner_bounds;
	private Paint runner_paint;
	private Paint labyrinth_paint;
	
	/** модель лабиринта */
	private LabyrinthModel labyrinth = null;
	/** обработчик событий лабиринта */
	private OnLabyrinthEventHandler handler = null;
	
	/**
	 * @see View
	 */
	public LabyrinthInnerView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		
		labyrinth = null;
		dip_scale = context.getResources().getDisplayMetrics().density;
		scalled_runner_bounds = (int)(dip_scale * ALLOWABLE_RUNNER_BOUNDS); // TODO разобраться с шаманством
		
		runner_paint = new Paint();
		runner_paint.setColor(0x8041c646/*R.color.labyrinth_runner*/);
		runner_paint.setStyle(Style.FILL);
		
		labyrinth_paint = new Paint();
		labyrinth_paint.setColor(0xff8c1006/*R.color.labyrinth_left*/);
		labyrinth_paint.setStyle(Style.FILL);
	}
	
	@Override
	protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
	{
		super.onSizeChanged(width, height, oldWidth, oldHeight);
		labyrinth = new LabyrinthModel(0, 0, width, height, scalled_runner_bounds);
		if (handler != null)
		{
			labyrinth.setOnLabyrinthEventHandler(handler);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		if (labyrinth == null) return false;
		switch (event.getAction())
		{
		case MotionEvent.ACTION_DOWN:
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			labyrinth.resetRunner();
			break;
		case MotionEvent.ACTION_MOVE:
			labyrinth.supplyRunnerPosition((int)event.getX(), (int)event.getY());
			break;
		}
		return true; 
	}
	
	@Override
	protected void onDraw(Canvas canvas)
	{
		if (labyrinth == null) return;
		// рисуем маршрут
		for (int i = 1, cnt = labyrinth.route.size()-1; i <= cnt; ++i)
		{
			final LabyrinthModel.Point p0 = labyrinth.route.get(i-1);
			final LabyrinthModel.Point p1 = labyrinth.route.get(i);
			canvas.drawRect(
				p0.x-ROUTE_WIDTH/2, p0.y-ROUTE_WIDTH/2,
				p1.x+ROUTE_WIDTH/2, p1.y+ROUTE_WIDTH/2,
				labyrinth_paint
			);

//отладка:final Point bndlt = new Point(Math.min(p0.x,p1.x)-scalled_runner_bounds, Math.min(p0.y,p1.y)-scalled_runner_bounds);
//отладка:final Point bndrb = new Point(Math.max(p0.x,p1.x)+scalled_runner_bounds, Math.max(p0.y,p1.y)+scalled_runner_bounds);
//отладка:canvas.drawRect(bndlt.x, bndlt.y, bndrb.x, bndrb.y, runner_paint);

			if (i == cnt) break;
			canvas.drawCircle(p1.x, p1.y, ROUTE_NODE_RADIUS, labyrinth_paint);
		}
		// рисуем узловые точки маршрута
		final LabyrinthModel.Point pf = labyrinth.route.get(0);
		final LabyrinthModel.Point pl = labyrinth.route.get(labyrinth.route.size()-1);
		canvas.drawCircle(pf.x, pf.y, ROUTE_TAIL_RADIUS, labyrinth_paint);
		canvas.drawCircle(pl.x, pl.y, ROUTE_TAIL_RADIUS, labyrinth_paint);
		// рисуем бегунок
		canvas.drawCircle(labyrinth.runner.x, labyrinth.runner.y, RUNNER_RADIUS, runner_paint);
		invalidate();
	}
	
	/**
	 * Инициализатор обработчика событий в лабиринте
	 * @param handler обработчик
	 */
	public void setOnLabyrinthEventHandler(OnLabyrinthEventHandler handler)
	{
		this.handler = handler;
		if (labyrinth != null)
		{
			labyrinth.setOnLabyrinthEventHandler(handler);
		}
	}
}
